package com.cc;

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * @Author C.
 * @Date 2019-03-31 15:12
 * <p>
 * Java8 中新增了接口的默认方法，简单来说就是让接口可以自己有实现方法，不许要实现类去实现。
 */
public class InterfaceTest {

    /**
     * 想象一种情况，你定义了一个接口A，假如里面有几个抽象方法。然后什么 B,C,D,E…
     * 一大堆类去实现了A接口里面的几个抽象方法。那么现在问题来了，如果要在A中新加一个抽象方法，
     * 那么所有的实现类都要去实现这个抽象方法，不是很麻烦吗？这个时候默认方法就派上用场了，
     * 只需要再A中自己实现这个新添加的方法就好了，
     * 所有的实现类也可以用了。最典型的例子，Iterable接口就增加了这么一个默认方法forEach
     */
    @Test
    public void test_forEach() {
        List<Integer> integers = new ArrayList<>();
        integers.add(1);
        integers.add(2);
        integers.add(3);
        integers.forEach(System.out::println);
    }

    /**
     * 使用也是很简单，创建一个MyFunction的实例，然后像普通实例方法的调用方式调用即可
     */
    @Test
    public void test_myFunction() {
        MyFunction<String> function = System.out::println;
        String str = function.getUpperCase("abc");
        Integer age = function.getAge();
        function.fun("This is demo...");
        System.out.println("str : " + str);
        System.out.println("age : " + age);
    }

    /**
     * 接口静态方法调用比较简单，类名. 方法 即可调用
     */
    @Test
    public void test_myFunction_for_static_function() {
        Integer num = MyFunction.toInteger("3");
        System.out.println(num);//3
    }
}

/**
 * 接口的默认方法
 * 接口的默认方法定义很简单，就是在方法返回值前使用 default 关键字修饰
 */
interface MyFunction<T> {
    void fun(T t);

    //默认方法
    default String getUpperCase(String str) {
        return str.toUpperCase();
    }

    //默认方法
    default Integer getAge() {
        return 23;
    }

    /**
     * 接口的静态方法
     * Java8 还允许接口中有静态方法
     */
    static Integer toInteger(String num) {
        return Integer.parseInt(num);
    }
}